/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>
#include <vector>
#include <map>
#include <optional>
#include <nlohmann/json.hpp>
#include "utils_noncopyable.h"
namespace El {
namespace Cloud {

class CloudModelImage {
    DISALLOW_COPY_AND_MOVE(CloudModelImage);

public:
    struct ImageData {
        const uint8_t *data;
        size_t size;
        int32_t width;
        int32_t height;
    };

    static CloudModelImage &GetInstance();

    void Start();

    void Stop();

    int32_t NewConversation();

    bool DeleteConversation(int32_t conversation_id);

    std::string AnalyzeImage(int32_t conversation_id, const ImageData &image_data, const std::string &prompt);

    std::string GenerateText(int32_t conversation_id, const std::string &prompt);

private:
    CloudModelImage();
    ~CloudModelImage() = default;

    bool InitConfig();
    static size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::string *s);
    std::string SendHttpRequest(const std::string &post_data, const std::string &url, const std::string &api_key);
    std::string ParseResponse(const std::string &response);
    std::string ParseTextGenerationResponse(const std::string &response);
    std::string ProcessMessage(int32_t conversation_id,
                               const nlohmann::json &message,
                               const std::optional<ImageData> &img_data);
    size_t CalculateImageTokens(int width, int height);
    size_t CalculateTextTokens(const std::string &text);
    size_t CalculateMessageTokens(const nlohmann::json &message, const std::optional<ImageData> &img_data);

private:
    // 针对 chat 与 vision 分别缓存密钥与端点
    std::string chat_api_key_;
    std::string chat_api_url_;
    std::string vision_api_key_;
    std::string vision_api_url_;
    std::map<int32_t, std::vector<std::pair<nlohmann::json, std::optional<ImageData>>>> conversations_;
    std::string model_chat_;
    std::string model_vision_;
    size_t max_context_length_{0};
    int32_t next_conversation_id_{0};
};

} // namespace Cloud
} // namespace El
